Olaf contributes Cetus track reader.
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Wed, 3 Aug 2005 01:20:59 +0000 (01:20 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Wed, 3 Aug 2005 01:20:59 +0000 (01:20 +0000)
gpsbabel/cetus.c

index 25808aff4887039d5d2c68e174fd2e582e57eec0..93b1bdfed1fa1fdaa62b48520e35057428f15229 100644 (file)
 
  */
 
+/*
+
+    History:
+    
+       2005/08/03:     Added track_read by O.K.
+                       (Thanx to Adam Schneider for additional information)
+
+*/
+    
 #include "defs.h"
 #include "coldsync/palm.h"
 #include "coldsync/pdb.h"
-
+#
 #define MYNAME "Cetus"
-#define MYTYPE  0x43577074     /* CWpt */
-#define MYCREATOR 0x63475053   /* cGPS */
+#define MYTYPE_WPT     0x43577074      /* CWpt */
+#define MYTYPE_TRK     0x7374726d      /* strm */
+
+#define MYCREATOR      0x63475053      /* cGPS */
+#define MYTRACK                0x44424c4b      /* DBLK */
 
 #define NOTESZ 4096
 #define DESCSZ 4096
@@ -43,7 +55,7 @@ typedef enum {
                        /* the icon field contains the garmin symbol number */
 } wpt_type;
 
-struct record {
+struct cetus_wpt_s {
        char type;      
        
        char   readonly;
@@ -88,6 +100,42 @@ struct record {
        pdb_16 category;
 };
 
+typedef struct cetus_track_head_s
+{
+       char            id[2];
+       char            version;
+       unsigned char   interval;
+       unsigned short  gps;
+       char            year;
+       char            month;
+       char            day;
+       char            hour;
+       char            min;
+       char            sec;
+       char            dsec;
+       char            tz;
+       char            desc;
+} cetus_track_head_t;
+
+#define TRACK_HEAD_SIZE sizeof(struct cetus_track_head_s)
+
+typedef struct cetus_track_point_s
+{
+       char hour;
+       char min;
+       char sec;
+       char msec;
+       char sat;
+       char hdop;
+       pdb_32 latitude;
+       pdb_32 longitude;
+       short speed;
+       short course;
+       pdb_32 elevation;
+} cetus_track_point_t;
+
+#define TRACK_POINT_SIZE sizeof(struct cetus_track_point_s)
+
 static FILE *file_in;
 static FILE *file_out;
 static const char *out_fname;
@@ -106,69 +154,156 @@ arglist_t cetus_args[] = {
        {0, 0, 0, 0 }
 };
 
-static void
-rd_init(const char *fname)
+static waypoint *
+read_track_point(cetus_track_point_t *data, const time_t basetime)
 {
-       file_in = xfopen(fname, "rb", MYNAME);
-}
+       int i, ilat, ilon;
+       waypoint *wpt;
 
-static void
-rd_deinit(void)
-{
-       fclose(file_in);
-       if ( dbname ) {
-           xfree(dbname);
-           dbname = NULL;
+       ilat = be_read32(&data->latitude);
+       ilon = be_read32(&data->longitude); 
+       
+       if (data->hour == -1 || data->min == -1 || data->sec == -1 ||
+           ilat == 2000000000 || ilon == 2000000000) return NULL;      /* At least one of basic data is not available */
+
+       wpt = waypt_new();
+                   
+       wpt->latitude = (double)ilat / 10000000.0;
+       wpt->longitude = (double)ilon / 10000000.0; 
+
+       i = be_read32(&data->elevation);
+       wpt->altitude = (i == -100000000) ? unknown_alt : (double) i / 100.0;
+       
+       if (data->sat != -1) wpt->sat = data->sat;
+       if (data->hdop != -1) wpt->hdop = (float) data->hdop / 10;
+       
+       i = be_read16(&data->speed);
+       if (i != 10000) wpt->speed = ((float) i / 10) * 0.514444;       /* meters/second */
+       i = be_read16(&data->course);
+       if (i != 4000) wpt->course = (float) i / 10;
+       
+       switch(data->hour / 32) /* extract fix */
+       {
+           case 0: break;                      /* no GPS */
+           case 1: wpt->fix = fix_none; break;
+           case 2: wpt->fix = fix_2d; break;
+           case 3: wpt->fix = fix_3d; break;
+           case 4: wpt->fix = fix_dgps; break;
        }
-}
+       
+       wpt->creation_time = basetime +
+           ((data->hour % 32) * 3600) + (data->min * 60) + data->sec;
 
-static void
-wr_init(const char *fname)
-{
-       file_out = xfopen(fname, "wb", MYNAME);
-       out_fname = fname;
+       return wpt;
 }
 
+       
 static void
-wr_deinit(void)
+read_tracks(const struct pdb *pdb)
 {
-       fclose(file_out);
-       if ( dbname ) {
-           xfree(dbname);
-           dbname = NULL;
+       struct pdb_record *pdb_rec;
+       int reclen, records, total, points, dropped;
+       char descr[DESCSZ];
+       cetus_track_head_t *head;
+       waypoint *wpt, *prev;
+       route_head *track;
+       time_t basetime;
+       
+       track = route_head_alloc();
+       track_add_head(track);
+
+       total = 0;
+       points = 0;
+       dropped = 0;
+       basetime = 0;
+       
+       for (pdb_rec = pdb->rec_index.rec; pdb_rec != NULL; pdb_rec = pdb_rec->next) 
+       {
+           int i, magic;
+           char *c = (char *)pdb_rec->data;
+
+           magic = be_read32(c);
+           if (magic != MYTRACK) 
+               fatal(MYNAME ": Invaid track data or unsupported version!\n");
+           
+           reclen = be_read32(c+4);
+           records = reclen / TRACK_POINT_SIZE;
+
+           c += 8;
+           prev = NULL;
+           
+           for (i = 0; i < records; i++, c += TRACK_POINT_SIZE)
+           {
+               switch(total++)
+               {
+                   struct tm tm;
+                   
+                   case 0:     /* track header */
+                       head = (cetus_track_head_t *)c; 
+                       if (head->id[0] != 'C' || head->id[1] != 'G') fatal(MYNAME ": Invalid track header!\n");
+                       
+                       memset(&tm, 0, sizeof(tm));
+                       tm.tm_mday = head->day;
+                       tm.tm_mon = head->month - 1;
+                       tm.tm_year = head->year + 100;
+                       basetime = mktime(&tm);
+                       break;
+                       
+                   case 1:     /* first part of description */
+                       strncpy(descr, c, 25);
+                       break;  
+                       
+                   case 2:     /* continued description */
+                       strncat(descr, c, sizeof(descr) - strlen(descr) - 1);
+                       if (strlen(descr) > 0)
+                           track->rte_desc = xstrdup(descr);
+                       break;  
+                       
+                   default:
+                       wpt = read_track_point((cetus_track_point_t *)c, basetime);
+                       if (wpt != NULL)
+                       {
+                           route_add_wpt(track, wpt);
+                           points++;
+                           
+                           /* Did we run over midnight ? */
+                           if ((prev != NULL) && (prev->creation_time > wpt->creation_time))
+                           {
+                               basetime += (24 * 3600);
+                               wpt->creation_time += (24 * 3600);
+                           }
+                           prev = wpt;
+                       }
+                       else
+                           dropped++;
+               }
+           
+           }
+       }
+
+       if (global_opts.verbose_status > 0)
+       {
+           printf(MYNAME ": Loaded %d track point(s) from source.\n", points);
+           if (dropped > 0)
+               printf(MYNAME ": ! %d dropped because of missing data (no time, no coordinates) !\n", dropped);
        }
 }
 
 static void
-data_read(void)
+read_waypts(const struct pdb *pdb)
 {
-       struct record *rec;
-       struct pdb *pdb;
+       struct cetus_wpt_s *rec;
        struct pdb_record *pdb_rec;
        char *vdata;
 
-       if (NULL == (pdb = pdb_Read(fileno(file_in)))) {
-               fatal(MYNAME ": pdb_Read failed\n");
-       }
-
-       if ((pdb->creator != MYCREATOR) || (pdb->type != MYTYPE)) {
-               fatal(MYNAME ": Not a Cetus file.\n");
-       }
-       
-       if (pdb->version < 1) {
-              fatal(MYNAME ": This file is from an obsolete beta version of Cetus GPS and is unsupported.\n");
-        }
-        if (pdb->version > 1) {
-              fatal(MYNAME ": This file is from an unsupported newer version of Cetus GPS.  It may be supported in a newer version of GPSBabel.\n");
-       }
-
-       for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) {
+       for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) 
+       {
                waypoint *wpt_tmp;
                int i;
 
                wpt_tmp = waypt_new();
 
-               rec = (struct record *) pdb_rec->data;
+               rec = (struct cetus_wpt_s *) pdb_rec->data;
                if ( be_read32(&rec->elevation) == -100000000 ) {
                        wpt_tmp->altitude = unknown_alt;
                }
@@ -176,10 +311,10 @@ data_read(void)
                        wpt_tmp->altitude = be_read32(&rec->elevation) / 100.0;
                }
                        
-               wpt_tmp->longitude = be_read32(&rec->longitude) / 10000000.0; 
                wpt_tmp->latitude = be_read32(&rec->latitude) / 10000000.0;
+               wpt_tmp->longitude = be_read32(&rec->longitude) / 10000000.0; 
                
-               if (rec->sat != 0xff)
+               if (rec->sat != 0xff) 
                        wpt_tmp->sat = rec->sat;
 
                i = be_read16(&rec->pdop);
@@ -199,7 +334,7 @@ data_read(void)
                if (be_read16(&rec->year) != 0xff) {
                        struct tm tm;
 
-                       memset (&tm, sizeof(tm), 0);
+                       memset (&tm, 0, sizeof(tm));
                        tm.tm_min = rec->min;
                        tm.tm_hour = rec->hour;
                        tm.tm_mday = rec->day;
@@ -223,6 +358,64 @@ data_read(void)
                waypt_add(wpt_tmp);
 
        } 
+}
+
+/* --------------------------------------------------------------------------- */
+
+static void
+rd_init(const char *fname)
+{
+       file_in = xfopen(fname, "rb", MYNAME);
+}
+
+static void
+rd_deinit(void)
+{
+       fclose(file_in);
+       if ( dbname ) {
+           xfree(dbname);
+           dbname = NULL;
+       }
+}
+
+static void
+wr_init(const char *fname)
+{
+       file_out = xfopen(fname, "wb", MYNAME);
+       out_fname = fname;
+}
+
+static void
+wr_deinit(void)
+{
+       fclose(file_out);
+       if ( dbname ) {
+           xfree(dbname);
+           dbname = NULL;
+       }
+}
+
+static void
+data_read(void)
+{
+       struct pdb *pdb;
+
+       if (NULL == (pdb = pdb_Read(fileno(file_in)))) {
+               fatal(MYNAME ": pdb_Read failed\n");
+       }
+
+       if (pdb->creator != MYCREATOR) fatal(MYNAME ": Not a Cetus file.\n");
+
+       switch(pdb->type)
+       {
+           case MYTYPE_TRK:
+               read_tracks(pdb);
+               break;
+               
+           case MYTYPE_WPT:
+               read_waypts(pdb);
+               break;
+       }
        free_pdb(pdb);
 }
 
@@ -230,7 +423,7 @@ data_read(void)
 static void
 cetus_writewpt(const waypoint *wpt)
 {
-       struct record *rec;
+       struct cetus_wpt_s *rec;
        static int ct;
        struct tm *tm;
        char *vdata;
@@ -397,7 +590,7 @@ data_write(void)
        opdb->name[PDB_DBNAMELEN-1] = 0;
        opdb->attributes = PDB_ATTR_BACKUP;
        opdb->ctime = opdb->mtime = current_time() + 2082844800U;
-       opdb->type = MYTYPE;  /* CWpt */
+       opdb->type = MYTYPE_WPT;  /* CWpt */
        opdb->creator = MYCREATOR; /* cGPS */
        opdb->version = 1;
 
@@ -434,7 +627,7 @@ data_write(void)
 
 ff_vecs_t cetus_vecs = {
        ff_type_file,
-       FF_CAP_RW_WPT,
+       { ff_cap_write | ff_cap_read, ff_cap_read, ff_cap_none },
        rd_init,
        wr_init,
        rd_deinit,